package com.nova.scenic.projectlibs.util.network;

import android.content.Context;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;

import com.nova.scenic.projectlibs.util.debug.MyLog;
import com.nova.scenic.projectlibs.util.debug.RegexExpressUtil;
import com.nova.scenic.projectlibs.util.io.StreamUtil;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SimpleNetwork {

    private static final String TAG = "SimpleNetwork";
    private static MyLog myLog = new MyLog(TAG);


    private String url = null;
    private URLConnection connection;
    private InputStream inputStream;
    private OutputStream outputStream;

    public SimpleNetwork(String url) {
        this.url = url;
    }

    private ResultError errorCode;


    public enum ResultError {

        ERROR_CODE_SERVER("无法连接到服务器"),
        SUCCESS("成功"),
        ERROR_CODE_MALFORMED_URL("URL格式不正确"), URLConnectionNullPoint("无法建立连接");

        ResultError(String describe) {
            this.describe = describe;
        }

        String describe;

        @Override
        public String toString() {
            return super.toString() + ":" + describe;
        }
    }

    public ResultError error() {
        return errorCode;
    }

    private void errorSet(ResultError errorCode) {
        this.errorCode = errorCode;
    }

    public int code() {
        try {
            connect();
        } catch (URLConnectionNullPointException e) {
            e.printStackTrace();
            return -1;
        }
        int code = -1;
        try {
            Map<String, List<String>> fields = getConnection().getHeaderFields();
            Collection<List<String>> values = fields.values();
            Iterator<List<String>> iterator = values.iterator();
            Pattern pattern = Pattern.compile(".+HTTP/.+(\\d{3}).+");
            while (iterator.hasNext()) {
                List<String> value = iterator.next();
                Matcher matcher = pattern.matcher(value.toString());
                if (matcher.matches()) {
                    String codeString = matcher.group(1);
                    return Integer.parseInt(codeString);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            //{null=[HTTP/1.1 200 OK], Content-Length=[0], Content-Type=[text/html;charset=UTF-8], Date=[Tue, 21 Jun 2016 02:11:44 GMT], Server=[Apache-Coyote/1.1], X-Android-Received-Millis=[1466475100909], X-Android-Response-Source=[NETWORK 200], X-Android-Selected-Transport=[http/1.1], X-Android-Sent-Millis=[1466475100894]}
        }

        if (code == -1) {
            myLog.error("get code error  " + getConnection().getHeaderFields() + " error " + error() + "  " + error().describe + "  " + error().ordinal());
        }

        return code;
    }

    public SimpleNetwork connect() throws URLConnectionNullPointException {
        if (connection == null) {
            URL url;
            try {
                url = new URL(this.url);
            } catch (MalformedURLException e) {
                e.printStackTrace();
                errorSet(ResultError.ERROR_CODE_MALFORMED_URL);
                return this;
            }

            try {
                connection = url.openConnection();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        if (connection == null) {
            errorSet(ResultError.URLConnectionNullPoint);
            throw new URLConnectionNullPointException();
        }

        return this;
    }

    public InputStream inputStream() {

        if(inputStream != null){
            return inputStream;
        }

        try {
            connect();
        } catch (URLConnectionNullPointException e) {
            e.printStackTrace();
            return null;
        }
        try {
            inputStream = getConnection().getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
            errorSet(ResultError.ERROR_CODE_SERVER);
        }

        return inputStream;
    }

    public OutputStream outputStream() {
        if(outputStream != null){
            return outputStream;
        }

        try {
            connect();
        } catch (URLConnectionNullPointException e) {
            e.printStackTrace();
            return null;
        }
        getConnection().setDoOutput(true);
        try {
            outputStream = getConnection().getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
            errorSet(ResultError.ERROR_CODE_SERVER);
        }
        return outputStream;
    }

    public URLConnection getConnection() {
        return connection;
    }

    public String string() throws MayNeedAlertErrorException {
        if (inputStream() == null) {
            throw new MayNeedAlertErrorException();
        }
        return StreamUtil.streamToString(inputStream(), null);
    }

    public SimpleNetwork post(String jsonString) throws MayNeedAlertErrorException {

        if (outputStream() == null) {
            throw new MayNeedAlertErrorException();
        }
        OutputStreamWriter writer = new OutputStreamWriter(outputStream());
        //write parameters
        try {
            writer.write(jsonString);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return this;
    }


    public static class URLConnectionNullPointException extends Exception {

    }

    public static class MayNeedAlertErrorException extends Exception {

    }


    public static boolean validateDataFormat(String s) {
        if (null == s)
            return false;

        try {
            //TODO(liuzd) 优化 这里标准的SDK无法访问到,需要以后反射处理
//			android.net.SimpleNetwork.numericToInetAddress(s);
        } catch (IllegalArgumentException e) {
            return false;
        }

        Pattern pattern = Pattern
                .compile(RegexExpressUtil.CHECK_IP);

        Matcher matcher = pattern.matcher(s);

        return matcher.matches();
    }

    public static boolean isNetworkConnected(Context context) {
        ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = manager.getActiveNetworkInfo();
        if (info == null) {
            MyLog.e("network info is null", -1);
            return false;
        }
        return info.isConnected();
    }

    public static boolean isEtheConnect(Context mContext) {
        ConnectivityManager manager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = manager.getActiveNetworkInfo();
        if (info == null) {
            return false;
        }

        if (info.getType() == ConnectivityManager.TYPE_ETHERNET) {
            return true;
        }
        return false;
    }

    public static boolean isWifiConnect(Context mContext) {
        WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);

        WifiInfo info = wifiManager.getConnectionInfo();
        MyLog.i(TAG, "isWifiConnect info is " + info);
        if (info == null) {
            return false;
        }

        try {
            List<WifiConfiguration> configs = wifiManager.getConfiguredNetworks();
            for (int i = 0; i < configs.size(); i++) {
                WifiConfiguration config = configs.get(i);

                //TODO(liuzd) 优化 这里标准的SDK无法访问到,需要以后反射处理
//                if(config.linkProperties.getAddresses() != null){
//                    return true;
//                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return false;
    }

    public static boolean isWEPPasswordInvalid(String paswd) {
        int length = paswd.length();
        String password = paswd.toString();
        // WEP-40, WEP-104, and 256-bit WEP (WEP-232?)
        if (((length == 10 || length == 16 || length == 26 || length == 32 || length == 58) &&
                password.matches("[0-9A-Fa-f]*")) || (length == 5 || length == 13)) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 获取联网的类型
     *
     * @param context
     * @return
     */
    public static int getConnectType(Context context) {
        ConnectivityManager lcm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo.State wifi = lcm.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState();

        if (wifi == NetworkInfo.State.CONNECTED || wifi == NetworkInfo.State.CONNECTING) {
            return CONNECTION_TYPE_WIFI;
        } else {
            NetworkInfo.State mobile = lcm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState();
            if (mobile == NetworkInfo.State.CONNECTED || mobile == NetworkInfo.State.CONNECTING) {

                // 主apn的uri
                Uri uri = Uri.parse("content://telephony/carriers/preferapn");
                Cursor mCursor = null;
                try {
                    mCursor = context.getContentResolver().query(uri, null, null, null, null);
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                try {
                    if (mCursor != null) {

                        // 游标移至第一条记录，当然也只有一条
                        mCursor.moveToNext();
                        String apn = mCursor.getString(mCursor.getColumnIndex("apn")).toLowerCase(Locale.getDefault());
                        if (apn != null && (apn.equals("3gnet") || apn.equals("cmnet") || apn.equals("uninet"))) {
                            return CONNECTION_TYPE_CM_NET;
                        } else {
                            String proxyStr = mCursor.getString(mCursor.getColumnIndex("proxy"));
                            if (proxyStr != null && proxyStr.trim().length() > 0) {
                                return CONNECTION_TYPE_WAP;
                            } else {
                                return CONNECTION_TYPE_CM_NET;
                            }
                        }
                    }
                } finally {
                    if (mCursor != null) {
                        mCursor.close();
                    }
                }
                return CONNECTION_TYPE_WAP;
            }
        }
        return CONNECTION_TYPE_NO_CONNECT;

    }
    public static final int CONNECTION_TYPE_WIFI = 0;
    public static final int CONNECTION_TYPE_CM_NET = 1;
    public static final int CONNECTION_TYPE_WAP = 2;
    public static final int CONNECTION_TYPE_NO_CONNECT = 3;
}
